
////////////////////////////////////////////////////////////////////////
// DirEntry
////////////////////////////////////////////////////////////////////////

/**
* DirEntry implements the entries of a directory node (RTDirNode)
    
* the info of the DirEntry in a RTDirNode block is organized as follows:
* +-------------+-----+------------------------+-----+-------------+
* | bounces[0]  | ... | bounces[2*dimension-1] | son | noOfData |
* +-------------+-----+------------------------+-----+-------------+
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace RStarTree
{
    public class DirEntry
    {
        public RTree myTree;                      // pointer to my R-tree
        public int son;                            // block # of son
        public RTNode sonPtr;              		// pointer to son if in main mem.
        public bool sonIsData;                // TRUE, if son is a data page
        public int dimension;                      // dimension of the box
        public float[] bounces;                    // the mbr of the box
        public int sonLevel;                      // level of the node pointed to
        public int noOfData;                    // amount of data entries behind the
        // son of this entry    
        public DirEntry(int _dimension, bool _sonIsData, RTree rt)
        {
            dimension = _dimension;
            sonIsData = _sonIsData;
            myTree = rt;
            bounces = new float[2 * dimension];
            sonPtr = null;
            noOfData = 0;
        }
        /**
        * copy the contents of this to another Direntry object
        */
        public void copyTo(DirEntry target)
        {
            target.dimension = dimension;
            target.son = son;
            target.sonPtr = sonPtr;
            target.sonLevel = sonLevel;
            target.sonIsData = sonIsData;
            target.noOfData = noOfData;
            for (int i = 0; i < 2 * dimension; i++)
            {
                target.bounces[i] = bounces[i];
            }
        }
        /**
        * Checks if point v is inside the entry's MBR
        */
        public bool isInside(float[] v)
        {
            int i;

            for (i = 0; i < dimension; i++)
            {
                if (v[i] < bounces[2 * i] || v[i] > bounces[2 * i + 1])
                    return false;
            }
            return true;
        }
        /**
         * Tests if the parameter mbr is inside or overlaps the MBR of the entry
         * Constants.INSIDE :inside
         * Constants.OVERLAP: overlap
         * Constants.S_NONE: None
        */
        public int interSection(float[] mbr)
        {
            bool inside;
            bool overlap;
            int i;

            overlap = true;
            inside = true;
            for (i = 0; i < dimension; i++)
            {
                if (mbr[2 * i] > bounces[2 * i + 1] || mbr[2 * i + 1] < bounces[2 * i])
                    overlap = false;
                if (mbr[2 * i] < bounces[2 * i] || mbr[2 * i + 1] > bounces[2 * i + 1])
                    inside = false;
            }
            if (inside)
                return Constants.INSIDE;
            else if (overlap)
                return Constants.OVERLAP;
            else
                return Constants.S_NONE;
        }
        /**
       * reads from the input stream the object's info
       * used by RTDirNode.readFromBuffer()
       */
        public void readFromBuffer(BinaryReader din)
        {
            for (int i = 0; i < 2 * dimension; ++i)
                bounces[i] = din.ReadSingle();
            son = din.ReadInt32();
            noOfData = din.ReadInt32();
        }
        /**
    * writes to the output stream the object's info
    * used by RTDirNode.write_to_buffer()
    */
        public void writeToBuffer(BinaryWriter dout)
        {
            for (int i = 0; i < 2 * dimension; ++i)
                dout.Write(bounces[i]);
            dout.Write(son);
            dout.Write(noOfData);
        }
        /************************************************************************/
        /* Get the size in number of bytes of a DirEntry                                                                      */
        /************************************************************************/
        public int getSize()
        {
            return 2 * dimension * Constants.SIZEOF_FLOAT + Constants.SIZEOF_INT
                            + Constants.SIZEOF_INT;
        }
        /**
        * returns the son_ptr (the node this entry points to
        * if the node is not in main memory, it it read
        * from disk (see RTDirNode/RTDataNode constructor)
        */
        public RTNode getSon()
        {
            if (sonPtr == null)
            {
                if (sonIsData)
                    sonPtr = new RTDataNode(myTree, son);
                else
                    sonPtr = new RTDirNode(myTree, son);
            }
            return sonPtr;
        }
        /**
        * returns true if the entry intersects the circle
        */
        public  bool isInterSecCircle(PPoint center, float radius)
        {
            return Utilities.isCircleInterSection(dimension, bounces, center, radius);
        }
        /**
   * returns true if the entry intersects the ring
   */
        public bool isRingInterSection(PPoint center, float radius1, float radius2)
        {
            return Utilities.isRingInterSection(dimension, bounces, center, radius1, radius2);
        }
        public void delete()
        {
            if (sonPtr != null)
                ((Node)sonPtr).delete();
        }


    }

}
